<?php

namespace App\service\goods;

use Exception;
use support\Log;
use support\Redis;
use think\facade\Db;
use App\service\nft\NftServices;
use crmeb\exceptions\AdminException;
use App\service\goods\GoodsComposeLogServices;
use think\db\exception\{DataNotFoundException, DbException, ModelNotFoundException};

class GoodsComposeServices
{
    /**
     * 提交合成
     * @param int $userId
     * @param int $id
     * @param int $num
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function composeSubmit(int $userId, int $id, int $num = 1)
    {
        $res = $this->composeList($userId, $id);

        $goodsInfo = $res['goodsInfo']; // 要合成的藏品信息
        $goodsCompose = $res['goodsCompose']; // 藏品合成条件


        if (strtotime($goodsInfo['issuer_date']) > time()) {
            throw new AdminException('此藏品暂未到合成时间，请您耐心等待！');
        }

        if ($goodsInfo['status'] == 0) {
            throw new AdminException('此藏品已下架！');
        }

        if ($goodsInfo['is_synthetic'] < 1) {
            throw new AdminException('此藏品暂未开启合成功能！');
        }

        if ($goodsInfo['current_have_num'] <= 0) {
            throw new AdminException('此藏品库存不足，暂时无法合成！');
        }

        foreach ($goodsCompose as $k => $v) {
            if ($v['nft_list_count'] == 0) {
                throw new AdminException('不满足合成条件！');
            }
            if ($v['nft_list_count'] < $v['num']) {
                throw new AdminException('不满足合成条件！');
            }

            // nft所有
            // 索引 idx_uid_goodsid_status_islock
            $nft_id_all_list = Db::name('nft_list')
                ->where('uid', $userId)
                ->where('goods_id', $v['condition_goods_id'])
                ->where('status', 'Active')
                ->force('idx_uid_goodsid_status_islock')
                ->select();


            $nft_id_null_count = 0;

            foreach ($nft_id_all_list as $item) {
                if (empty($item['nft_id'])) {
                    $nft_id_null_count = $nft_id_null_count + 1;
                }
            }

            // 可用数量
            $available_count = $v['nft_list_count'] - $nft_id_null_count;

            if ($available_count < $v['num']) {
                throw new AdminException('合成条件中有藏品在上链途中，请耐心等待！');
            }

        }
//        $prefix = env('REDIS_PREFIX');
//        $ttl_seconds = env('REDIS_TTL_SECONDS');

        $userInfo = Db::name('user')->where('id', $userId)->find();

        // 开始销毁 并 创建 合成藏品

        //开始事务
        Db::startTrans();
        try {

            // 减库存
            if (!Db::name('goods')->where('id', $id)->dec('current_have_num')->update()) {
                throw new AdminException('网络错误请稍后再试1');
            }

            // 查看减完以后的库存
            $stock = Db::name('goods')->where('id', $id)->value('current_have_num');

            if ($stock < 0) {
                throw new AdminException('此藏品库存不足，暂时无法合成！');
            }

            // 加销量
            if (!Db::name('goods')->where('id', $id)->inc('sold')->update()) {
                throw new AdminException('网络错误请稍后再试1');
            }

            $description = '合成藏品名称：' . $goodsInfo['name'] . '，合成消耗：';
            $goods_compose_log_many = [];

            foreach ($goodsCompose as $k => $v) {
                // 挨个 销毁 如果销毁后 nft数量为空 删除 nft折叠
                $where = [];
                $where[] = ['uid', '=', $userId];
                $where[] = ['goods_id', '=', $v['condition_goods_id']];
                $where[] = ['status', '=', 'Active'];

                $description .= $v['condition_goods_name'] . ' *' . (int)$v['num'] . '个     ';

                $many = Db::name('nft_list')
                    ->where('uid', $userId)
                    ->where('goods_id', $v['condition_goods_id'])
                    ->where('status', 'Active')
                    ->limit((int)$v['num'])
                    ->force('idx_uid_goodsid_status_islock')
                    ->select();


                foreach ($many as $key => $val) {
                    $goods_compose_log_many[] = [
                        'condition_goods_id' => $v['condition_goods_id'],
                        'condition_goods_name' => $v['condition_goods_name'],
                        'nft_id' => $val['nft_id'],
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s'),
                    ];
                }

                $result = Db::name('nft_list')
                    ->where('uid', $userId)
                    ->where('goods_id', $v['condition_goods_id'])
                    ->where('status', 'Active')
                    ->limit((int)$v['num'])
                    ->force('idx_uid_goodsid_status_islock')
                    ->update(['status' => 'Burned', 'updated_at' => date('Y-m-d H:i:s')]);

                if (!$result) {
                    throw new AdminException('网络错误请稍后再试2');
                }

                // 如果 关于这个藏品 一个都没有了  那么 折叠数据也就不存在了 做删除
                $search = Db::name('nft_list')
                    ->where('uid', $userId)
                    ->where('goods_id', $v['condition_goods_id'])
                    ->where('status', 'Active')
                    ->find();

                if (!$search) {

                    $nft = Db::name('nft')
                        ->where('uid', $userId)
                        ->where('goods_id', $v['condition_goods_id'])
                        ->find();

                    if ($nft) {
                        Db::name('nft')->where('id', $nft['id'])->delete();
                    }
                }

            }

            // 开始 创建 合成藏品
            $nftServices = new NftServices();
            $nftServices->addNft($userId, $id, $userInfo, $goodsInfo);

            $goodsComposeLogServices = new GoodsComposeLogServices();

            $return = $goodsComposeLogServices->addLog(
                $userInfo,
                $goodsInfo,
                $goodsCompose,
                $goods_compose_log_many,
                $description
            );

            if (!$return) {
                throw new AdminException("网络错误请稍后重试5！");
            }

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw new AdminException($e->getMessage());
        }

        return true;
    }

    /**
     * 合成条件列表
     * @param int $userId 用户id
     * @param int $id 要合成的藏品id
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function composeList(int $userId, int $id)
    {
        $goodsInfo = Db::name('goods')->where('id', $id)->find();

        if (empty($goodsInfo)) {
            throw new AdminException('藏品id不存在！');
        }
        $goodsCompose = Db::name('goods_compose')->where('goods_id', $id)->select()->all(); // 合成条件

        $condition_goods_ids = array_column($goodsCompose, 'condition_goods_id');

        $where = [];
        $where[] = ['a.uid', '=', $userId];
        $where[] = ['a.goods_id', 'in', $condition_goods_ids];

        // 合成条件中的 每一个 我目前分别有几个
        $list = Db::name('nft')->alias('a')
            ->join('nft_list b', 'a.id = b.nft_pk_id and b.status = "Active"')
            ->group('a.id')
            ->where($where)
            ->field('a.*,count(b.id) as nft_list_count')
            ->order('a.updated_at desc')
            ->select()
            ->all();

//        halt($list);
        foreach ($goodsCompose as $k => $v) {
            for ($i = 0; $i < count($list); $i++) {
                if ($v['condition_goods_id'] == $list[$i]['goods_id']) {
                    $nft_list_count = $list[$i]['nft_list_count'];
                    $goodsCompose[$k]['nft_list_count'] = $nft_list_count;
                    $goodsCompose[$k]['num_string'] = $nft_list_count . ' / ' . $v['num'];
                }
            }
        }

        foreach ($goodsCompose as $k => $v) {
            if (!isset($v['num_string'])) {
                $goodsCompose[$k]['num_string'] = '0 / ' . $v['num'];
                $goodsCompose[$k]['nft_list_count'] = 0;
            }
        }

        return [
            'have_count' => Db::name('nft_list')->where('uid', $userId)->where('goods_id', $id)->where('status', 'Active')->count() ?? 0,
            'goodsInfo' => $goodsInfo, // 要合成的藏品信息
            'goodsCompose' => $goodsCompose // 藏品合成条件
        ];
    }

}
